#!/usr/bin/python3
# Copyright (c) 2009-2018 Canonical Ltd
#
# AUTHOR:
# Michael Vogt <mvo@ubuntu.com>
# Balint Reczey <rbalint@ubuntu.com>
#
# unattended-upgrade-shutdown - helper that checks if a
# unattended-upgrade is in progress and waits until it exists
#
# This file is part of unattended-upgrades
#
# unattended-upgrades is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation; either version 2 of the License, or (at
# your option) any later version.
#
# unattended-upgrades is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with unattended-upgrades; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

import dbus
import signal
import datetime
import logging
import logging.config
import os.path
import os
import sys
import getpass
import configparser
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GLib
from optparse import OptionParser, Values
from threading import Event 
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.jobstores.memory import MemoryJobStore
from apscheduler.executors.pool import ThreadPoolExecutor,ProcessPoolExecutor
import random
import time
import subprocess
# from pytz import utc
from gettext import gettext as _
import gettext
#deprecated
UNATTENDED_UPGRADE_CONFIG_FILE_PATH="/var/lib/unattended-upgrades/unattended-upgrade.conf"
UNATTENDED_UPGRADE_TIMESTAMP = "/var/lib/unattended-upgrades/unattended-upgrades-timestamp"


UNATTENDED_UPGRADE_POLICY_FILE_PATH="/var/lib/unattended-upgrades/unattended-upgrades-policy.conf"
LOG_PATH = "/var/log/kylin-unattended-upgrades/unattended-upgrades-shutdown.log"
TIMESTAMP_PATH="/var/lib/kylin-software-properties/template/kylin-source-status"
ACTION_INSTALL = 1
ACTION_CHECK_RESOLVER = 3
ACTION_DOWNLOADONLY = 4
        
def get_random_time(time_interval):
    now = datetime.datetime.now()
    try:
        start_time = datetime.datetime.strptime(time_interval.split("-")[0],"%H:%M")
        end_time = datetime.datetime.strptime(time_interval.split("-")[1],"%H:%M")
        start=datetime.datetime(now.year,now.month,now.day,start_time.hour,start_time.minute,0,0)
        end=datetime.datetime(now.year,now.month,now.day,end_time.hour,end_time.minute,0,0)
        time_diff = int((end-start).total_seconds())
        if time_diff<0:
            time_diff=time_diff+86400
        delta = random.randint(0,time_diff)
        actual_time = start+datetime.timedelta(seconds=delta)
        time_diff = int((actual_time - now).total_seconds())
        if time_diff<0:
            return actual_time+datetime.timedelta(seconds=86400)
        return actual_time
    except Exception as e:
        logging.error(_("illegal time format:%s")%e)
        return now+datetime.timedelta(seconds=random.randint(0,86400))

def ReadValueFromFile(file,section,option):
    config=configparser.ConfigParser(allow_no_value=True)
    config.optionxform = str
    try:
        config.read(file)
        value = config[section][option]
    except Exception as e:
        logging.error(_("read config file error:%s")%e)
        return ''
    return value

def WriteValueToFile(file,section,option,value):
    config=configparser.ConfigParser(allow_no_value=True)
    config.optionxform = str
    config.add_section(section)
    config.set(section,option,value)
    config.write(open(file,"w"))
  
def signal_term_handler(signal,frame):
    # type: (int, object) -> None
    logging.warning("SIGTERM received, will stop")
    os._exit(1)

def Predownload():
    logging.info(_("predownload task start"))
    return unattended_upgrades_shutdown.Download()
    
def Download():
    logging.info(_("download task start"))
    return unattended_upgrades_shutdown.Download()
    
def Install():
    logging.info(_("install task start"))
    return unattended_upgrades_shutdown.Install()
    
def Upgrade():
    logging.info(_("upgrade task start"))
    return unattended_upgrades_shutdown.Install()
           
class AutoUpgradePolicy():
    def __init__(self) -> None:
        self.autoupgradepolicy = {}
        if os.path.exists(UNATTENDED_UPGRADE_POLICY_FILE_PATH):
            config=configparser.ConfigParser(allow_no_value=True)
            config.optionxform = str
            config.read(UNATTENDED_UPGRADE_POLICY_FILE_PATH)
            for option in config.options('autoUpgradePolicy'):
                self.autoupgradepolicy.update({option:config['autoUpgradePolicy'][option]})
        logging.info(_("auto upgrade policy:"))
        for key in self.autoupgradepolicy.keys():
            # logging.debug(_("initial policy configure:"))
            logging.debug("%s:%s"%(key,self.autoupgradepolicy[key]))        
       
    def SetOptionValue(self,option,value):
        self.autoupgradepolicy.update({option:value})
   
    def GetOptionValue(self,option):
        try:
            return self.autoupgradepolicy[option]
        except Exception:
            return '' 
                                                         
class UnattendedUpgradesShutdown():
    def __init__(self, options):
        # type: (Values) -> None
        self.options = options
        self.init_events_flags()
        self.init_policy_config()
        self.init_scheduler()
        self.init_dbus_connections() 
    
    def init_events_flags(self):
        logging.info(_("init events and flags"))
        self.update_detect_status = False
        self.update_detect_event = Event()
        self.update_list = []
        self.resolve_depend_status = False
        self.resolve_depend_status_event = Event()
        self.remove_pkgs = []
        self.install_finish_status = False
        self.install_finish_status_event = Event()
        self.install_finish_group = []
        self.download_finish_status = False
        self.download_finish_status_event = Event()
        self.download_finish_group = []
        self.backup_start_result = False
        self.backup_finish_result = False
        self.backup_finish_event = Event()
    
    def init_policy_config(self):
        logging.info(_("init policy config"))
        self.autoupgradepolicy = AutoUpgradePolicy()
    
    def init_scheduler(self):
        jobstores = {'default': MemoryJobStore()}
        executors = {'default':ThreadPoolExecutor(1),'processpool':ProcessPoolExecutor(1)}
        job_defaults = {'coalesce':False,'max_instances':1}
        self.background_scheduler = BackgroundScheduler(jobstores=jobstores,executors=executors,job_defaults=job_defaults)
        updatedays = 1
        try:
            updatedays = int(self.autoupgradepolicy.GetOptionValue('updateDays'))
        except Exception as e:
            logging.error(_("get update days error:%s")%e)
        try:
            if self.autoupgradepolicy.GetOptionValue('autoUpgradeState') == 'on':
                if self.autoupgradepolicy.GetOptionValue('downloadMode') == 'timing':
                    random_time = get_random_time(self.autoupgradepolicy.GetOptionValue('downloadTime'))
                    self.background_scheduler.add_job(Download,trigger='interval',days=updatedays,\
                        start_date=random_time,id='download',replace_existing=True)
                if self.autoupgradepolicy.GetOptionValue('installMode') == 'timing':
                    random_time = get_random_time(self.autoupgradepolicy.GetOptionValue('installTime'))
                    self.background_scheduler.add_job(Install,trigger='interval',days=updatedays,\
                        start_date=random_time,id='install',replace_existing=True)
            if self.autoupgradepolicy.GetOptionValue('preDownload') == 'on':
                random_time = get_random_time(self.autoupgradepolicy.GetOptionValue('preDownloadTime'))
                self.background_scheduler.add_job(Predownload,trigger='interval',days=updatedays,\
                    start_date=random_time,id='predownload',replace_existing=True)                
        except Exception as e:
            logging.error(_("job initial error:%s")%e)
        self.background_scheduler.start()    
        with open(LOG_PATH,'a+') as f:
            self.background_scheduler.print_jobs(out=f)
        joblist = self.background_scheduler.get_jobs()
        for job in joblist:    
            logging.debug(_("initial job:%s,next run time:%s")%(job.id,job.next_run_time))    
    
    def load_systemupgrade_dbus_config(self):
        logging.debug(_("init system upgrade dbus connections"))
        self.update_proxy = self.system_bus.get_object('com.kylin.systemupgrade','/com/kylin/systemupgrade',follow_name_owner_changes=True)
        self.update_interface = dbus.Interface(self.update_proxy,dbus_interface='com.kylin.systemupgrade.interface')
        self.update_proxy.connect_to_signal('UpdateDetectFinished',self.update_detect_finished_handler)                                        
        self.update_proxy.connect_to_signal('UpdateDependResloveStatus',self.update_depend_resolve_status)                                           
        self.update_proxy.connect_to_signal('UpdateDloadAndInstStaChanged',self.update_download_install_status)
        self.update_proxy.connect_to_signal('UpdateInstallFinished',self.update_install_finished)                                        
        self.update_proxy.connect_to_signal('UpdateDownloadFinished',self.update_download_finished)               
    
    def load_strategy_dbus_config(self):
        logging.debug(_("init strategy dbus connections"))
        self.upgrade_strategy_proxy = self.system_bus.get_object('com.kylin.UpgradeStrategies','/com/kylin/UpgradeStrategies',follow_name_owner_changes=True)
        self.upgrade_strategy_interface = dbus.Interface(self.upgrade_strategy_proxy,dbus_interface='com.kylin.UpgradeStrategies.interface') 
        self.upgrade_strategy_proxy.connect_to_signal("PropertyChanged",self.property_changed_handler)
        self.upgrade_strategy_proxy.connect_to_signal("UpgradeAllNow",self.upgrade_all_now_handler) 
        
    def load_backup_dbus_config(self):
        logging.debug(_("init backup dbus connections"))
        self.backup_proxy = self.system_bus.get_object('com.kylin.backup','/',follow_name_owner_changes=True)
        self.backup_interface = dbus.Interface(self.backup_proxy,dbus_interface='com.kylin.backup.manager')                                                                                                                                      
        self.backup_proxy.connect_to_signal('sendStartBackupResult',self.backup_start_handler)                                       
        self.backup_proxy.connect_to_signal('sendBackupResult',self.backup_result_handler)                                          
        self.backup_proxy.connect_to_signal('sendRate',self.send_rate_handler) 
    
    def load_sys_dbus_config(self):
        logging.debug(_("load sys dbus config"))
        self.sys_proxy = self.system_bus.get_object('org.freedesktop.DBus','/org/freedesktop/DBus')
        self.sys_proxy.connect_to_signal('NameOwnerChanged',self.name_owner_changed)
         
    def init_dbus_connections(self):
        logging.debug(_("loading dbus configures..."))
        DBusGMainLoop(set_as_default=True)
        self.loop = GLib.MainLoop()
        self.system_bus = dbus.SystemBus()
        self.load_sys_dbus_config()
        self.load_systemupgrade_dbus_config()
        self.load_strategy_dbus_config()
        self.load_backup_dbus_config()
                                                 
    def name_owner_changed(self,busname,oldname,newname):
        if (busname == 'com.kylin.UpgradeStrategies'):
            logging.debug("name owner changed:%s,%s,%s"%(busname,oldname,newname))
        elif(busname == 'com.kylin.systemupgrade'):
            logging.debug("name owner changed:%s,%s,%s"%(busname,oldname,newname))
        elif(busname == 'com.kylin.backup'):
            logging.debug("name owner changed:%s,%s,%s"%(busname,oldname,newname))
        else:
            pass
        
    def property_changed_handler(self,property, value): 
        logging.info(_("property change:%s:%s")%(property,value))    
        self.autoupgradepolicy.SetOptionValue(property,value)             
        self.ExecutePolicy(property,value)
        with open(LOG_PATH,'a+') as f:
            self.background_scheduler.print_jobs(out=f)
        joblist = self.background_scheduler.get_jobs()
        for job in joblist:    
            logging.debug(_("job:%s,next run time:%s")%(job.id,job.next_run_time))    
    
    def upgrade_all_now_handler(self):
        logging.info(_("upgrade all now sinal received"))
        delta = random.randint(0,int(self.autoupgradepolicy.GetOptionValue('randomRange')))
        run_date = datetime.datetime.now() + datetime.timedelta(minutes=delta)
        self.background_scheduler.add_job(Upgrade,'date', run_date = run_date,id="upgrade",\
            max_instances=1,replace_existing=True)  
        with open(LOG_PATH,'a+') as f:
            self.background_scheduler.print_jobs(out=f) 
        joblist = self.background_scheduler.get_jobs()
        for job in joblist:    
           logging.debug(_("job:%s,next run time:%s")%(job.id,job.next_run_time))    
                                       
    def update_detect_finished_handler(self,success,updatelist,error_status,error_cause):
        logging.info(_("update detect finished:sucess:%s,updatelist:%s,error_status:%s,error_cause:%s")\
            %(success,",".join(updatelist),error_status,error_cause))
        self.update_detect_status = success
        self.update_list = updatelist
        self.update_detect_event.set()
        
    def update_depend_resolve_status(self,resolver_status,remove_status,remove_pkgs,pkg_raw_description,delete_description,error_string,error_desc):
        logging.info(_("update depend resove status:%s,remove status:%s,remove pkgs:%s,pkg raw description:%s,delete_descrition:%s,error string:%s,error desc:%s")\
            %(resolver_status,remove_status,",".join(remove_pkgs),",".join(pkg_raw_description),",".join(delete_description),error_string,error_desc))
        self.resolve_depend_status = resolver_status
        self.remove_pkgs = remove_pkgs
        self.resolve_depend_status_event.set()
        
    def update_download_install_status(self,group,progress,status,details):
        logging.debug(_("%s update progress:%d,status:%s,details:%s")%(",".join(group),progress,status,details))
        
    def update_install_finished(self,success,group,error_string,error_desc):
        logging.info(_("update install finisih success:%s,group:%s,error string:%s,error desc:%s")\
            %(success,",".join(group),error_string,error_desc))
        self.install_finish_status = success
        self.install_finish_group=group
        self.install_finish_status_event.set()
        
    def update_download_finished(self,success,group,error_string,error_desc):
        logging.info(_("update download finisih success:%s,group:%s,error string:%s,error desc:%s")\
            %(success,",".join(group),error_string,error_desc))
        self.download_finish_status = success    
        self.download_finish_group = group
        self.download_finish_status_event.set()
    
    def backup_start_handler(self,result):
        logging.debug(_("backup start result:%d")%result)
        if result == 31 or result == 30:    
            self.backup_start_result = True
        else:                    
            self.backup_start_result = False
        self.backup_finish_event.set()
                    
    def backup_result_handler(self,result):
        logging.debug(_("backup result:%s")%result)
        if result:                    
            self.backup_finish_result = True 
        else:
            self.backup_finish_result = False 
        self.backup_finish_event.set()   
        
    def send_rate_handler(self,sta,pro):
        logging.debug(_("backup status:%d,progress:%d")%(sta,pro))
    
    def run(self):
        if self.options.wait_for_signal:
            logging.debug(_("Waiting for signal to start operation "))
            self.loop.run()
        elif options.download_only:
            logging.debug(_("runing a download job"))
            return self.Download()
        elif options.install_only:
            logging.debug(_("runing an install job"))
            return self.Install()
        elif options.upgrade:
            logging.debug(_("runing an upgrade job"))
            return self.Install()
        else:
            logging.info(_("illegal options"))
        return True
    
    def print_jobs(self):
        with open(LOG_PATH,'a+') as f:
            self.background_scheduler.print_jobs(out=f)
    
    def list_jobs(self):
        joblist = self.background_scheduler.get_jobs()
        for job in joblist:    
            logging.debug(_("job:%s,next run time:%s")%(job.id,job.next_run_time))
            
    def remove_job(self,job_id):
        if self.background_scheduler.get_job(job_id):
            self.background_scheduler.remove_job(job_id)    
    
    def ExecutePolicy(self,property,value):
        updatedays = 1
        try:
            updatedays = int(self.autoupgradepolicy.GetOptionValue('updateDays'))
        except Exception as e:
            logging.error(e)
        try:      
            if property == 'autoUpgradeState':
                if value == 'on':
                    if self.autoupgradepolicy.GetOptionValue('downloadMode') == 'timing':
                        random_time = get_random_time(self.autoupgradepolicy.GetOptionValue('downloadTime'))
                        self.background_scheduler.add_job(Download,trigger='interval',days=updatedays,\
                            start_date=random_time,id='download',replace_existing=True)
                    if self.autoupgradepolicy.GetOptionValue('installMode') == 'timing':
                        random_time = get_random_time(self.autoupgradepolicy.GetOptionValue('installTime'))
                        self.background_scheduler.add_job(Install,trigger='interval',days=updatedays,\
                            start_date=random_time,id='install',replace_existing=True)
                elif value == 'off':
                    self.remove_job('download')
                    self.remove_job('install')
                else:
                    pass                 
            elif property == 'downloadMode':
                if value == 'timing':
                    if self.autoupgradepolicy.GetOptionValue('autoUpgradeState') == 'on':
                        random_time = get_random_time(self.autoupgradepolicy.GetOptionValue('downloadTime'))
                        self.background_scheduler.add_job(Download,trigger='interval',days=updatedays,\
                            start_date=random_time,id='download',replace_existing=True)
                elif value == 'manual':
                    self.remove_job('download')
                else:
                    pass    
            elif property == 'downloadTime':  
                if self.autoupgradepolicy.GetOptionValue('autoUpgradeState') == 'on' and \
                    self.autoupgradepolicy.GetOptionValue('downloadMode') == 'timing': 
                    random_time = get_random_time(value)
                    self.background_scheduler.add_job(Download,trigger='interval',days=updatedays,\
                        start_date=random_time,id='download',replace_existing=True)      
            elif property == 'installMode':  
                if value == 'timing':
                    if self.autoupgradepolicy.GetOptionValue('autoUpgradeState') == 'on':
                        random_time = get_random_time(self.autoupgradepolicy.GetOptionValue('installTime'))
                        self.background_scheduler.add_job(Install,trigger='interval',days=updatedays,\
                            start_date=random_time,id='install',replace_existing=True)
                elif value == 'manual':
                    self.remove_job('install')
                elif value == 'bshutdown':
                    self.remove_job('install')
                else:
                    pass
            elif property == 'installTime':  
                if self.autoupgradepolicy.GetOptionValue('autoUpgradeState') == 'on' and \
                    self.autoupgradepolicy.GetOptionValue('installMode') == 'timing':
                    random_time = get_random_time(value)
                    self.background_scheduler.add_job(Install,trigger='interval',days=updatedays,\
                        start_date=random_time,id='install',replace_existing=True)
            elif property == 'preDownload':  
                if value == 'on':
                    random_time = get_random_time(self.autoupgradepolicy.GetOptionValue('preDownloadTime'))
                    self.background_scheduler.add_job(Predownload,trigger='interval',days=updatedays,\
                        start_date=random_time,id='predownload',replace_existing=True)           
                elif value == 'off':
                    self.remove_job('predownload')
                else:
                    pass 
            elif property == 'preDownloadTime':  
                if self.autoupgradepolicy.GetOptionValue('preDownload') == 'on':
                    random_time = get_random_time(value)
                    self.background_scheduler.add_job(Predownload,trigger='interval',days=updatedays,\
                        start_date=random_time,id='predownload',replace_existing=True)        
            elif property == 'updateDays':
                if self.autoupgradepolicy.GetOptionValue('preDownload') == 'on':
                    random_time = get_random_time(self.autoupgradepolicy.GetOptionValue('preDownloadTime'))
                    self.background_scheduler.add_job(Predownload,trigger='interval',days=updatedays,\
                        start_date=random_time,id='predownload',replace_existing=True) 
                if self.autoupgradepolicy.GetOptionValue('autoUpgradeState') == 'on':
                    if self.autoupgradepolicy.GetOptionValue('downloadMode') == 'timing': 
                        random_time = get_random_time(self.autoupgradepolicy.GetOptionValue('downloadTime'))
                        self.background_scheduler.add_job(Download,trigger='interval',days=updatedays,\
                            start_date=random_time,id='download',replace_existing=True) 
                    if self.autoupgradepolicy.GetOptionValue('installMode') == 'timing':
                        random_time = get_random_time(self.autoupgradepolicy.GetOptionValue('installTime'))
                        self.background_scheduler.add_job(Install,trigger='interval',days=updatedays,\
                            start_date=random_time,id='install',replace_existing=True)           
            else:
                logging.info(_("other options:%s:%s")%(property,value))
        except Exception as e:
            logging.error(_("policy execute error:%s")%e) 
    
    def Backup(self): 
        logging.info(_("start backup"))
        backup_partition_status = self.backup_interface.Mount_backup_partition()
        logging.info(_("backup partition status:%d")%backup_partition_status)
        if backup_partition_status not in [0,5]:
            logging.error(_("backup partition error:%d")%backup_partition_status)
            return False
        status_code,result = self.backup_interface.getBackupState()
        logging.debug(_("backup state code:%d,%s")%(status_code,result))
        if result == 0 and status_code == 99:
            pass
        else:   
            return False
        backup_name = _("unattended upgrades")
        create_note = ''
        inc_note = ''
        userName=getpass.getuser()
        uid=os.getuid()
        self.backup_finish_event.clear()
        self.backup_start_result=True
        self.backup_finish_result=True
        self.backup_interface.autoBackUpForSystemUpdate_noreturn(backup_name,create_note,inc_note,userName,uid)
        self.backup_finish_event.wait()
        logging.debug(_("backup start result:%s,backup result:%s")%(self.backup_start_result,self.backup_finish_result))
        if (self.backup_start_result and self.backup_finish_result):              
            return True
        else:
            return False
        
    def Download(self):
        logging.debug(_("start download"))
        self.update_detect_event.clear()
        self.UpdateDetect()
        self.update_detect_event.wait()
        logging.debug(_("update detect finish:%s,%s")%(self.update_detect_status,",".join(self.update_list)))
        if self.update_detect_status and len(self.update_list)>0:
            pass
        elif not self.update_detect_status and 'kylin-system-updater' in self.update_list:
            logging.info(_("self update finished"))
        else:
            return False
        self.resolve_depend_status_event.clear()
        self.DistUpgradeForAuto(ACTION_CHECK_RESOLVER)
        # self.DistUpgradeAll(False)
        self.resolve_depend_status_event.wait()
        logging.debug(_("resolve dependency status:%s,%s")%(self.resolve_depend_status,",".join(self.remove_pkgs)))
        if self.resolve_depend_status and len(self.remove_pkgs)==0:
            pass
        else:
            return False
        self.download_finish_status_event.clear()
        self.DistUpgradeForAuto(ACTION_DOWNLOADONLY)
        self.download_finish_status_event.wait()
        logging.debug(_("download finish status:%s,%s")%(self.download_finish_status,",".join(self.download_finish_group)))
        if self.download_finish_status and len(self.download_finish_group)>0:
            pass
        else:
            return False
        return True
        
    def Install(self):
        logging.debug(_("start install"))
        self.update_detect_event.clear()
        self.UpdateDetect()
        self.update_detect_event.wait()
        logging.debug(_("update detect finish:%s,%s")%(self.update_detect_status,",".join(self.update_list)))
        if self.update_detect_status and len(self.update_list)>0:
            pass
        elif not self.update_detect_status and 'kylin-system-updater' in self.update_list:
            logging.info(_("self update finished"))
        else:
            return False
        self.resolve_depend_status_event.clear()
        self.DistUpgradeForAuto(ACTION_CHECK_RESOLVER)
        # self.DistUpgradeAll(False)
        self.resolve_depend_status_event.wait()
        logging.debug(_("resolve dependency status:%s,%s")%(self.resolve_depend_status,",".join(self.remove_pkgs)))
        if self.resolve_depend_status and len(self.remove_pkgs)==0:
            pass
        else:
            return False
        needbackup = self.autoupgradepolicy.GetOptionValue('backupbeforeinstall')
        logging.debug(_("checking if need backup:%s")%needbackup)
        if needbackup == 'on':
            if self.Backup():
                logging.debug(_("backup success"))
            else:
                logging.debug(_("backup failed"))
                return False    
        self.install_finish_status_event.clear()
        self.DistUpgradeForAuto(ACTION_INSTALL)
        self.install_finish_status_event.wait()        
        logging.debug(_("install finish status:%s,%s")%(self.install_finish_status,",".join(self.install_finish_group)))
        if self.install_finish_status and len(self.install_finish_group)>0:
            self.reboot_if_required()
        else:
            return False
        return True        
      
    def UpdateDetect(self):
        return self.update_interface.UpdateDetect()
    
    def DistUpgradeAll(self,is_install):
        return self.update_interface.DistUpgradeAll(is_install) 
    
    def mount_backup_partition(self):
        return self.backup_interface.Mount_backup_partition()

    def DistUpgradeForAuto(self,mode):
        return self.update_interface.DistUpgradeForAuto(mode)
    
    def get_backup_state(self):
        return self.backup_interface.getBackupState()

    def get_backup_comment_for_systemupdate(self):
        return self.backup_interface.getBackupCommentForSystemUpdate()
    
    def auto_backup_for_system_update_noreturn(self,timeStamp,create_note,inc_note,userName,uid):
        self.backup_interface.autoBackUpForSystemUpdate_noreturn(timeStamp,create_note,inc_note,userName,uid)
        return        
    
    def reboot_if_required(self):
        needreboot = self.autoupgradepolicy.GetOptionValue('automaticReboot')
        when = self.autoupgradepolicy.GetOptionValue('automaticRebootTime')
        logging.debug(_("check if need reboot:%s when:%s")%(needreboot,when))
        if needreboot == "on":
            try:
                output = subprocess.check_output(["/sbin/shutdown","-r",when],shell=False)
                logging.debug(output)
            except Exception as e:
                logging.error(_("Failed to issue shutdown: %s")%e)
                return False

    
if __name__ == "__main__":
    gettext.bindtextdomain("unattended-upgrades","/usr/share/locale")
    gettext.textdomain("unattended-upgrades")
    parser = OptionParser()
    parser.add_option("", "--debug",
                      action="store_true", dest="debug",
                      default=False,help="print debug messages")   
    parser.add_option("", "--download-only",
                      action="store_true", dest="download_only",
                      default=False,help="only download without install")
    parser.add_option("", "--install-only",
                      action="store_true", dest="install_only",
                      default=False,help="only install without download")
    parser.add_option("", "--upgrade",
                      action="store_true", dest="upgrade",
                      default=False,help="upgrade all packages") 
    parser.add_option("", "--wait-for-signal",
                      action="store_true", dest="wait_for_signal",
                      default=False,
                      help="wait for TERM signal before starting operation")
    (options, args) = parser.parse_args()
    logdir = "/var/log/kylin-unattended-upgrades/"
    if not os.path.exists(logdir):
        os.makedirs(logdir)
    logfile = os.path.join(logdir, "unattended-upgrades-shutdown.log")
    if options.debug:
        logging.basicConfig(format='%(asctime)s-%(name)s-%(levelname)s-%(message)s',datefmt='%Y-%m-%d,%H:%M:%S',level=logging.DEBUG,stream=sys.stdout)
    else:
        logging.basicConfig(format='%(asctime)s-%(name)s-%(levelname)s-%(message)s',datefmt='%Y-%m-%d,%H:%M:%S',level=logging.DEBUG,filename=logfile) 
    signal.signal(signal.SIGTERM, signal_term_handler)
    signal.signal(signal.SIGHUP, signal.SIG_IGN)
    logging.info(_("unattended upgrade start options:%s")%(" ".join(sys.argv)))
    unattended_upgrades_shutdown = UnattendedUpgradesShutdown(options)
    sys.exit(unattended_upgrades_shutdown.run())    